package com.example.jbmsuppliers.bluetooth.le;

import android.app.Service;

import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * Created by root on 16-10-16.
 */
public abstract class Resource extends Service
{
	public Resource ( int count )
	{
		this.count = count;
		this.resource = new ArrayBlockingQueue(count);

		for ( Integer i = 0; i < count; i ++ )
			resource.add(count-i-1);
		lifes = new Life[count];
		lifemap = new HashMap<String, Integer>();

		lifethread = new LifeThread();
		lifethread.start();

		resname = UUID.randomUUID().toString();
	}

	public Resource()
	{
		this(10);
	}

	protected int count;
	protected BlockingQueue resource;
	protected Life[] lifes;
	protected HashMap<String,Integer> lifemap;

	protected String resname;

	private LifeThread lifethread = null;
	private Object life_mutex = new Object();

	private class LifeThread extends Thread
	{
		@Override
		public void run()
		{
			int i = 0;
			int sleeptimes = 0;
			boolean sleep = false;

			while(true)
			{
				if ( i >= count )
				{
					i = 0;

					if (sleeptimes==0)
						try
						{
							sleep(5);
						} catch (Exception e)
						{

						}

					sleeptimes = 0;
				}

				synchronized (life_mutex)
				{
					if ( lifes[i] != null )
					{
						try
						{
							lifes[i].Wakeup();
							sleep = true;
						} catch (Exception e)
						{

						}
					}
				}

				if ( sleep )
				{
					sleep = false;
					try
					{
						sleep(16);
					} catch (Exception e)
					{

					}
				}
				i++;
			}
		}
	}


	public boolean Add (Life life)
	{
		int index;

		try
		{
			index = (Integer) resource.take();
		}catch (Exception e)
		{
			return false;
		}

		synchronized (life_mutex)
		{
			ResKey key = new ResKey( index );
			life.BindLifeName( key );

			this.lifes[index] = life;
			life.SetStatus( Life.inqueue );

			if ( life.GetUniqueIndex() != null )
				lifemap.put((String)life.GetUniqueIndex(),index);
		}

		life.BindPool( this );
		return true;
	}

	public boolean Drop ( ResKey key )
	{
		boolean back = false;

		synchronized (life_mutex)
		{
			if (this.lifes[key.index] != null)
				if (key.key.equals(this.lifes[key.index].GetLifeName().key))
				{
					if ( this.lifes[key.index].GetUniqueIndex() != null )
						lifemap.remove((String)this.lifes[key.index].GetUniqueIndex());
					this.lifes[key.index].SetStatus(Life.leftqueue);
					this.lifes[key.index] = null;

					back = true;
				}
		}

		if ( back )
			try
			{
				resource.put(key.index);
			}catch (Exception e)
			{
				return false;
			}

		return true;
	}

	public Life Get ( ResKey key, Object result, String uniqueidx )
	{
		if ( uniqueidx == null && ( key.index < 0 || key.key == null ) )
			return null;

		synchronized (life_mutex)
		{
			if ( uniqueidx != null )
			{
				Integer index = lifemap.get(uniqueidx);

				if ( index != null )
					return this.lifes[index];
				else
					return null;
			}else if ( this.lifes[key.index] != null )
				if ( key.key.equals(this.lifes[key.index].GetLifeName().key))
				{
					Life rtn = this.lifes[key.index];
					if ( rtn.IsLast(result))
						Drop( key );
					return rtn;
				}else
					return null;
			else
				return null;
		}
	}
}
